package com.zhaowenhao.hello.spring.framework.webmvc.servlet;

import com.zhaowenhao.hello.spring.framework.annotation.WHController;
import com.zhaowenhao.hello.spring.framework.annotation.WHRequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:只适用于WHController的适配器
 * @Author: zwh
 * @Date: 2020-08-03
 * @Time: 18:59
 */
public class WHHandlerAdapter {

    protected Map<String, Integer> paramIndex = new HashMap<String, Integer>();
    ;


    public WHModelAndView handle(HttpServletRequest req, HttpServletResponse resp, WHHandlerMapping handler) throws InvocationTargetException, IllegalAccessException {
        /**
         * 1.得到参数类型和索引的对应位置关系
         */
        //得到所有参数类型
        Class<?>[] parameterTypes = handler.getMethod().getParameterTypes();
        //得到所有参数的注解
        Annotation[][] parameterAnnotations = handler.getMethod().getParameterAnnotations();

        //提取request 和 response
        for (int i = 0; i < parameterTypes.length; i++) {
            Class param = parameterTypes[i];
            if (param == HttpServletRequest.class || param == HttpServletResponse.class) {
                paramIndex.put(param.getName(), i);
            }
        }

        for (int i = 0; i < parameterAnnotations.length; i++) {
            for (Annotation annotation : parameterAnnotations[i]) {
                if (annotation instanceof WHRequestParam) {
                    String name = ((WHRequestParam) annotation).value();
                    if (!"".equals(name)) {
                        paramIndex.put(name.trim(), i);
                    }
                }
            }
        }

        /**
         * 2. 开始提取请求中的参数值并进行转化
         */

        //创建临时保存的实参
        Object[] params = new Object[parameterTypes.length];

        //拿到所有的请求参数集
        Map<String, String[]> parameterMap = req.getParameterMap();


        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            //拿到当前的值
            String value = Arrays.toString(entry.getValue()).replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("\\s", "");

            //判断当前的键值是否匹配形参
            if (!paramIndex.containsKey(entry.getKey())) {
                continue;
            }
            Integer index = paramIndex.get(entry.getKey());
            //根据形参类型做转换
            params[index] = convert(parameterTypes[index], value);
        }


        //匹配req和res
        if (paramIndex.containsKey(HttpServletRequest.class.getName())) {
            params[paramIndex.get(HttpServletRequest.class.getName())] = req;
        }
        if (paramIndex.containsKey(HttpServletResponse.class.getName())) {
            params[paramIndex.get(HttpServletResponse.class.getName())] = resp;
        }

        /**
         * 3.进行反射调用
         */
        Object result = handler.getMethod().invoke(handler.getController(), params);
        if (result == null || result == Void.class) {
            return null;
        }
        if (handler.getMethod().getReturnType() == WHModelAndView.class) {
            return (WHModelAndView) result;
        }
        return null;
    }

    private Object convert(Class<?> parameterType, String value) {
        if (parameterType == Integer.class) {
            return Integer.valueOf(value);
        } else if (parameterType == Double.class) {
            return Double.valueOf(value);
        }
        return value;
    }
}
